import base from "./base.controller";
import md5 from "md5";

const fs = require('fs');
const path = require('path');
const assert = require('assert');
const lodash = require('lodash');

export default class extends base {

    async _initialize() {
        await super._initialize();
    }

    async index() {

        // let Model = this.model('admin/Module');
        await this.render('admin/module/index', {
            setupStatus: [{key: false, title: '未安装'}, {key: true, title: '已安装'}],
        });
    }

    async table() {
        const p = this.query.page || 1;

        const post = this.post;
        const id = post.id.trim();
        const isSetup = post.isSetup;
        const keywords = post.keywords.trim();

        this.logger.debug(post);

        //构造查询条件
        let queryParams = {};

        //正则表达式查询
        if (keywords !== "") {
            queryParams = {
                $or: [
                    {name: {$regex: keywords, $options: "$i"}},
                    {alias: {$regex: keywords, $options: "$i"}}
                ]
            }
        }

        //等值查询
        if (isSetup !== "") {
            queryParams = Object.assign(queryParams, {isSetup: isSetup});
        }

        //id属性要单独查找,不支持正则表达式
        if (id !== "") {
            try {
                queryParams = {
                    _id: koahub.mongoose.Types.ObjectId(id)
                }
            } catch (err) {
                this.error('没找到符合条件的记录');
                return;
            }
        }
        this.logger.debug(`search queryParams:${JSON.stringify(queryParams)}`);

        const pageSize = await this.common.config('LIST_ROWS');
        const pageEntity = await this.model('admin/Module').findPage({
            page: p,
            pageSize: pageSize
        }, '', queryParams, {}, {isSetup: 'desc', name: 'asc'}, function (error, results) {
            // console.log(results);
        });

        await this.render('admin/module/table', {
            records: pageEntity.data,
            pager: this.common.ajaxPage(p, pageEntity.pagination.rowCount, pageEntity.pagination.pageSize)
        });
    }

    async uninstall() {
        const id = this.post.id || "";
        const ids = id.split(',');
        const Model = this.model('admin/Module');
        for (const i of ids) {
            const module = await Model.findByIdAndUpdate(i, {isSetup: false}).exec();

            if (module) {
                // this.logger.debug(module);
                // this.logger.debug(koahub.paths);

                const script_path = path.join(__dirname, `/../../${module['name']}/info/uninstall.js`);
                this.logger.debug(`module install script file path : ${script_path}`);
                if (fs.existsSync(script_path)) {
                    const uninstall = koahub.common.requireDefault(script_path);
                    if (typeof uninstall === 'function') {
                        await uninstall();
                    }
                }
            }
        }
        this.success('/admin/module/index', '模块卸载成功');
    }

    async install() {
        const id = this.post.id || "";
        const ids = id.split(',');
        let Model = this.model('admin/Module');
        for (const i of ids) {
            const module = await Model.findByIdAndUpdate(i, {isSetup: true}).exec();

            if (module) {
                let script_path;

                script_path = path.join(__dirname, `/../../${module['name']}/info/install.js`);
                if (fs.existsSync(script_path)) {
                    this.logger.debug(`install module from ${script_path}`);
                    const install = koahub.common.requireDefault(script_path);
                    if (typeof install === 'function') {
                        await install();
                    }
                }

                //安装后台管理菜单
                script_path = path.join(__dirname, `/../../${module['name']}/info/menu.js`);
                if (fs.existsSync(script_path)) {
                    this.logger.debug(`install mudule menu from ${script_path}`);
                    const install = koahub.common.requireDefault(script_path);
                    if (typeof install === 'function') {
                        await install();
                    }
                }
            }

        }
        this.success('/admin/module/index', '模块安装成功');
    }

    async delete() {
        const id = this.post.id || "";
        const ids = id.split(',');
        const Model = this.model('admin/Module');

        //先卸载模块，在从数据库中删除记录

        for (const i of ids) {

            const module = await Model.findById(i,).exec();
            if (module) {
                //卸载模块
                const script_path = path.join(__dirname, `/../../${module['name']}/info/uninstall.js`);
                this.logger.debug(`module install script file path : ${script_path}`);
                if (fs.existsSync(script_path)) {
                    const uninstall = koahub.common.requireDefault(script_path);
                    if (typeof uninstall === 'function') {
                      await uninstall();
                    }
                }
                //删除数据库记录
                await Model.findByIdAndRemove(i).exec();
            }

        }
        this.success('/admin/module/index', '模块删除成功');
    }

    walk(dir) {

        dir = path.resolve(this.app, dir);

        const exist = fs.existsSync(dir);
        if (!exist) {
            return;
        }

        const files = fs.readdirSync(dir);
        let list = [];

        for (let file of files) {
            if (fs.statSync(path.resolve(dir, file)).isDirectory()) {
                list = list.concat(this.walk(path.resolve(dir, file)));
            } else {
                list.push(path.resolve(dir, file));
            }
        }

        return list;
    }

    async reset() {
        //遍历所有模块的信息，更新不一致的信息，必须有info/info.js文件
        const dir = path.join(__dirname, `/../..`);
        // this.logger.debug(dir);

        const exist = fs.existsSync(dir);
        if (!exist) {
            return;
        }

        const files = fs.readdirSync(dir);
        let list = []; //保存有模块配置信息的模块名称列表
        for (let module of files) {
            if (fs.statSync(path.resolve(dir, module)).isDirectory()) {
                //判断是否存在模块配置文件:module_name/info/info.js
                if (fs.existsSync(path.resolve(dir, module, 'info', 'info.js'))) {
                    list.push(module);
                }
            }
        }

        const Module = this.model('admin/Module');

        //删除不在列表中的模块
        await Module.remove({name: { $nin: list }}).exec();

        this.logger.debug(list);


        for (const module of list) {
            //加载配置文件
            const info = koahub.common.requireDefault(path.resolve(dir, module,'info', 'info'));
            //检查配置文件格式是否合格
            assert(lodash.isPlainObject(info), 'module info must export as plain object.');

            let oldValue = await Module.findOne({name: module}).exec();
            if (oldValue) {
                //更新
                await Module.findByIdAndUpdate(oldValue._id, info);
            } else {
                //创建
                await Module.create(info);
            }
        }

        this.success('/admin/module/index', '模块信息同步成功');
    }

    async add() {
        if (this.isPost()) {
            const module = this.post;
            this.model('admin/Module').saveOrUpdate(module);
            this.success('/admin/module/index', '保存成功');
        } else {
            //Edit
            const Model = this.model('admin/Module');
            if (this.query.id) {
                const module = await Model.findOne({_id: this.query.id}).exec();
                await this.render('admin/module/add', {module: module});
            } else {
                this.error('admin/module/index','不能手动添加模块。')
            }
        }
    }
}